package org.zoomdev.zoom.common.caster;

import org.apache.commons.lang3.StringUtils;
import org.zoomdev.zoom.common.json.JSON;
import org.zoomdev.zoom.common.utils.DateTimeUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

class BasicTypes {
    static class Boolean2BigDecimal implements ValueCaster {

        @Override
        public Object to(Object src) {
            Boolean number = (Boolean) src;
            return new BigDecimal(number ? 1 : 0);
        }
    }

    static class Boolean2Byte implements ValueCaster {
        @Override
        public Object to(Object src) {
            return ((Boolean) src) ? (byte) 1 : (byte) 0;
        }
    }

    static class Boolean2Char implements ValueCaster {
        @Override
        public Object to(Object src) {
            return ((Boolean) src) ? '1' : '\0';
        }
    }

    static class Boolean2Double implements ValueCaster {
        @Override
        public Object to(Object src) {
            return ((Boolean) src) ? (double) 1 : (double) 0;
        }
    }

    static class Boolean2Float implements ValueCaster {
        @Override
        public Object to(Object src) {
            return ((Boolean) src) ? (float) 1 : (float) 0;

        }
    }

    static class Boolean2Int implements ValueCaster {
        @Override
        public Object to(Object src) {
            return ((Boolean) src) ? 1 : 0;
        }
    }

    static class Boolean2Long implements ValueCaster {
        @Override
        public Object to(Object src) {
            return ((Boolean) src) ? 1L : 0L;
        }
    }

    static class Number2Boolean implements ValueCaster {

        @Override
        public Object to(Object src) {
            return ((Number) src).intValue() == 0 ? Boolean.FALSE : Boolean.TRUE;
        }

    }

    static class Number2Byte implements ValueCaster {

        @Override
        public Object to(Object src) {
            return ((Number) src).byteValue();
        }
    }

    static class Number2Char implements ValueCaster {

        @Override
        public Object to(Object src) {
            return (char) ((Number) src).shortValue();
        }

    }

    static class Number2Double implements ValueCaster {

        @Override
        public Object to(Object src) {
            return ((Number) src).doubleValue();
        }

    }

    static class Number2Float implements ValueCaster {

        @Override
        public Object to(Object src) {
            return ((Number) src).floatValue();
        }

    }

    static class Number2Integer implements ValueCaster {

        @Override
        public Object to(Object src) {
            return ((Number) src).intValue();
        }

    }

    static class Number2Long implements ValueCaster {

        @Override
        public Object to(Object src) {
            return ((Number) src).longValue();
        }
    }

    static class Number2Short implements ValueCaster {

        @Override
        public Object to(Object src) {
            return ((Number) src).shortValue();
        }

    }

    static class String2BigDecimal implements ValueCaster {

        @Override
        public Object to(Object src) {
            String number = (String) src;
            return new BigDecimal(number);
        }
    }

    static class String2BigInteger implements ValueCaster {
        @Override
        public Object to(Object src) {
            String value = (String) src;     //毫秒
            return new BigInteger(value);
        }
    }

    static class String2Boolean implements ValueCaster {

        @Override
        public Object to(Object src) {
            return Boolean.parseBoolean((String) src);
        }

    }

    static class String2Byte implements ValueCaster {

        @Override
        public Object to(Object src) {
            return Byte.parseByte((String) src);
        }

    }

    static class String2ByteArray implements ValueCaster {

        @Override
        public Object to(Object src) {
            String str = (String) src;
            return Base64.decodeFast(str);
        }
    }

    static class String2Char implements ValueCaster {

        @Override
        public Object to(Object src) {
            return ((String) src).charAt(0);
        }

    }

    static class String2Class implements ValueCaster {

        @Override
        public Object to(Object src) {
            try {
                return Class.forName((String) src);
            } catch (ClassNotFoundException e) {
                throw new CasterException(e);
            }
        }

    }


    static class String2Double implements ValueCaster {

        @Override
        public Object to(Object src) {
            return Double.parseDouble((String) src);
        }

    }

    static class String2Float implements ValueCaster {

        @Override
        public Object to(Object src) {
            return Float.parseFloat((String) src);
        }

    }

    static class String2Integer implements ValueCaster {

        @Override
        public Object to(Object src) {
            String str = ((String) src).trim();
            if (str.contains(".")) {
                return (int) Double.parseDouble(str);
            }
            if (str.length() == 0) {
                return 0;
            }
            return Integer.parseInt(str);
        }

    }

    static class Short2BigDecimal implements ValueCaster {

        @Override
        public Object to(Object src) {
            Short number = (Short) src;
            return new BigDecimal(number);
        }
    }

    static class Double2BigDecimal implements ValueCaster {

        @Override
        public Object to(Object src) {
            Double number = (Double) src;
            return new BigDecimal(number);
        }
    }

    static class Double2Boolean implements ValueCaster {

        @Override
        public Object to(Object src) {
            return src.equals(0.0d) ? Boolean.FALSE : Boolean.TRUE;
        }
    }

    static class Date2Integer implements ValueCaster {

        @Override
        public Object to(Object src) {
            Date date = (Date) src;
            return (int) (date.getTime() / 1000);
        }

    }

    static class Date2Long implements ValueCaster {

        @Override
        public Object to(Object src) {
            Date date = (Date) src;
            return date.getTime();
        }

    }

    static class Date2SqlDate implements ValueCaster {

        @Override
        public Object to(Object src) {
            Date date = (Date) src;
            return new java.sql.Date(date.getTime());
        }

    }

    static class Date2SqlTime implements ValueCaster {

        @Override
        public Object to(Object src) {
            Date date = (Date) src;
            return new Time(date.getTime());
        }
    }


    static class Date2Timestamp implements ValueCaster {

        @Override
        public Object to(Object src) {
            Date date = (Date) src;
            return new Timestamp(date.getTime());
        }
    }

    static class Long2BigDecimal implements ValueCaster {

        @Override
        public Object to(Object src) {
            Long number = (Long) src;
            return new BigDecimal(number);
        }
    }

    static class Long2BigInteger implements ValueCaster {
        @Override
        public Object to(Object src) {
            Long value = (Long) src;     //毫秒
            return BigInteger.valueOf(value);
        }
    }

    static class Long2Timestamp implements ValueCaster {
        @Override
        public Object to(Object src) {
            Long value = (Long) src;     //毫秒
            return new Timestamp(value);
        }
    }

    static class String2Bean implements ValueCaster {

        private final Class<?> clazz;

        public String2Bean(Class<?> clazz) {
            this.clazz = clazz;
        }

        @Override
        public Object to(Object src) {
            String str = (String) src;
            try {
                return JSON.parse(str, clazz);
            } catch (Throwable t) {
                return null;
            }
        }
    }

    static class String2BeanProvider extends CasterProviderWithClass {

        @Override
        public ValueCaster getCaster(Class<?> srcType, Class<?> toType) {
            if (CharSequence.class.isAssignableFrom(srcType) && !Utils.isSimple(toType)) {
                return new String2Bean(toType);
            }
            return null;
        }


    }


    static class String2Long implements ValueCaster {

        @Override
        public Object to(Object src) {
            String str = ((String) src).trim();
            if (str.contains(".")) {
                return (long) Double.parseDouble(str);
            }
            if (str.length() == 0) {
                return 0;
            }
            return Long.parseLong(str);
        }

    }

    static class String2Short implements ValueCaster {

        @Override
        public Object to(Object src) {
            return Short.parseShort((String) src);
        }

    }

    static class Timestamp2Date implements ValueCaster {
        @Override
        public Object to(Object src) {
            Timestamp timestamp = (Timestamp) src;
            return new Date(timestamp.getTime());
        }
    }


    static class String2Timestamp implements ValueCaster {
        ValueCaster caster;

        public String2Timestamp() {
            caster = Caster.wrap(String.class, Date.class);
        }

        @Override
        public Object to(Object src) {
            String date = (String) src;
            Date dat = (Date) caster.to(date);
            return new Timestamp(dat.getTime());
        }
    }


    static class Integer2BigDecimal implements ValueCaster {

        @Override
        public Object to(Object src) {
            Integer number = (Integer) src;
            return new BigDecimal(number);
        }

    }

    static class BigInteger2Long implements ValueCaster {
        @Override
        public Object to(Object src) {
            BigInteger value = (BigInteger) src;     //毫秒
            return value.longValue();
        }
    }

    static class BigDecimal2Boolean implements ValueCaster {

        @Override
        public Object to(Object src) {
            return ((BigDecimal) src).doubleValue() == 0.0d ? Boolean.FALSE : Boolean.TRUE;
        }
    }

    static class Float2Boolean implements ValueCaster {

        @Override
        public Object to(Object src) {
            return src.equals(0.0f) ? Boolean.FALSE : Boolean.TRUE;
        }
    }


    /**
     * 字符串转日期转换器
     */
    static class String2Date implements ValueCaster {

        static final String2Date STRING_2_DATE= new String2Date();

        @Override
        public Object to(Object source) {
            String dateString = (String) source;
            if (dateString == null || dateString.length() < 8) {
                throw new CasterException("Invalid date string: " + dateString);
            }

            try {
                if (StringUtils.isNumeric(dateString)) {
                    // 处理纯数字格式
                    return parseNumericDate(dateString);
                } else {
                    // 处理带分隔符格式
                    return parseFormattedDate(dateString);
                }
            } catch (ParseException e) {
                throw new CasterException("Failed to parse date: " + dateString, e);
            }
        }

        private Date parseNumericDate(String numericString) throws ParseException {
            if (numericString.length() % 2 > 0 &&
                    numericString.length() != DateTimeUtils.COMPACT_DATE_TIME_WITH_MILLIS_PATTERN.length()) {
                throw new CasterException("Invalid numeric date format: " + numericString);
            }

            String formatPattern = DateTimeUtils.COMPACT_DATE_TIME_WITH_MILLIS_PATTERN
                    .substring(0, numericString.length());
            return new SimpleDateFormat(formatPattern).parse(numericString);
        }

        private Date parseFormattedDate(String formattedString) throws ParseException {
            String formatPattern = DateTimeUtils.DATE_TIME_WITH_MILLIS_PATTERN
                    .substring(0, formattedString.length());
            return new SimpleDateFormat(formatPattern).parse(formattedString);
        }
    }

    /**
     * 日期转字符串转换器
     */
    static class Date2String implements ValueCaster {
        @Override
        public Object to(Object source) {
            Date date = (Date) source;
            return new SimpleDateFormat(DateTimeUtils.DATE_TIME_PATTERN).format(date);
        }
    }

    /**
     * 时间戳转字符串转换器
     */
    static class Timestamp2String implements ValueCaster {
        @Override
        public Object to(Object source) {
            Timestamp timestamp = (Timestamp) source;
            return new SimpleDateFormat(DateTimeUtils.DATE_TIME_PATTERN).format(timestamp);
        }
    }
}
